# -*- coding: utf-8 -*-
"""
Module Description: 同盟国信息缓存
Date: 2020/09/30
Author: sxj
"""

from collections import defaultdict

from pyshare.bll.utils.share.base_cache_info import BaseCacheInfo
from pyshare.redis_cache.share.allies_cache import AlliesCountryInfoCache
from pyshare.dal.repository_impl import CrossAlliesCountryRepository


class AlliesCountryInfo(BaseCacheInfo):
    default_var = {'AlliesId': "", 'CountryId': 0, 'AlliesNo': 0, 'CountryName': "", 'CountryLv': 1,
                   'NameChangeTimes': 0}


CountryInfoList = [AlliesCountryInfo]


class AlliesCountryCache(object):
    """
    同盟国国家信息缓存
    """

    country_info_cache = AlliesCountryInfoCache()

    @staticmethod
    def get_key(allies_id, country_id):
        s, seq = "_", (allies_id, str(country_id))
        return s.join(seq)

    @staticmethod
    def get_key_list(allies_id_list, country_id_list):
        """
        生成缓存key: AlliesId_CountryId
        :param allies_id_list: ['allies_id_one', 'allies_id_two']
        :param country_id_list: [[1], [1, 2, 3]]
        :return: ['allies_id_one_1', 'allies_id_two_1', 'allies_id_two_2', 'allies_id_two_3']
        """
        key_list = list()
        for a_id, c_id_list in zip(allies_id_list, country_id_list):
            a_id_list = [a_id] * len(c_id_list)
            for a, c in zip(a_id_list, c_id_list):
                s, seq = "_", (a, str(c))
                key_list.append(s.join(seq))
        return key_list

    @staticmethod
    def split_allies_country_id(allies_country_id_list):
        """
        解析AlliesId_CountryId字符串
        :param allies_country_id_list: ['AlliesId_1', 'AlliesId_2']
        :return: {'AlliesId': [1,2]}
        """
        allies_country_id_dict = defaultdict(list)
        for a_c_id in allies_country_id_list:
            allies_id, country_id = a_c_id.split("_")
            allies_country_id_dict[allies_id].append(int(country_id))
        return allies_country_id_dict

    @classmethod
    def get_many_country_info_from_db(cls, allies_country_id_dict, info_index=0):
        """
        从DB获取同一战区多个国家数据
        :param allies_country_id_dict: {'allies_id': [1,2,3]}
        :param info_index: CountryInfoList下标
        :return: {AlliesId_CountryId: {CountryInfo}}  e.p.: {"014f78ceca5711eab02d6e6bfc94fda6_1": {CountryInfo}}
        """
        country_dict = dict()
        for allies_id, country_id_list in allies_country_id_dict.items():
            country_list = CrossAlliesCountryRepository.filter_country_info_by_allies_id_list(allies_id, country_id_list)
            for country in country_list:
                key = cls.get_key(country['AlliesId'], country['CountryId'])
                country_info = dict()
                for field in CountryInfoList[info_index]().get_fields():
                    if field == 'AlliesNo':
                        allies_no = 0 if not country.get('AlliesNo', 0) else country.get('AlliesNo', 0)
                        country_info[field] = allies_no
                    else:
                        country_info[field] = country.get(field)
                country_dict[key] = CountryInfoList[info_index](**country_info)
        return country_dict

    @classmethod
    def set_country_cache(cls, allies_id, country_id, country_dict):
        """
        将一个国家信息加入缓存
        :param allies_id:
        :param country_id:
        :param country_dict:
        :return:
        """
        allies_country_id = cls.get_key(allies_id, country_id)
        cls.country_info_cache.set_country_cache(allies_country_id, country_dict, need_dumps=True)

    @classmethod
    def set_many_country_cache(cls, information_dict):
        """
        将多个国家信息加入缓存
        :param information_dict: {AlliesId_CountryId: {CountryInfo}}
        :return:
        """
        cls.country_info_cache.set_many_country_cache(information_dict, need_dumps=True)

    @classmethod
    def get_country_info_from_cache_db(cls, allies_id, country_id, info_index=0):
        """
        从缓存获取一个国家数据，获取不到从DB获取，并写入缓存
        :param allies_id:
        :param country_id:
        :param info_index: CountryInfoList下标
        :return:
        """
        if country_id:
            allies_country_id = cls.get_key(allies_id, country_id)
            country_info = cls.country_info_cache.get_country_cache(allies_country_id, need_loads=True)
            if country_info:
                return CountryInfoList[info_index](**country_info)

            # 缓存中无数据，从DB获取，并写入缓存
            country_dict = cls.get_many_country_info_from_db({allies_id: [country_id]})
            if country_dict:
                cls.set_country_cache(allies_id, country_id, country_dict[allies_country_id]._asdict())

            return country_dict.get(allies_country_id, {})
        else:
            country_info = AlliesCountryInfo.default_var
            return CountryInfoList[info_index](**country_info)

    @classmethod
    def get_many_country_info_from_cache_db(cls, allies_country_id_dict, info_index=0):
        """
        从缓存获取多个国家数据，获取不到从DB获取，并写入缓存
        :param allies_country_id_dict: {'allies_id': [1,2,3]}
        :param info_index: CountryInfoList下标
        :return: {AlliesId_CountryId: CountryInfo实例}
        """
        info_dict = dict()
        not_found_list = list()
        if not allies_country_id_dict:
            return info_dict

        # 拼接key
        allies_id_list, country_id_list = allies_country_id_dict.keys(), allies_country_id_dict.values()
        country_id_list = [c for c in country_id_list if c]
        all_key_list = cls.get_key_list(allies_id_list, country_id_list)
        if not all_key_list:
            return info_dict

        # 获取数据
        country_info_list = cls.country_info_cache.get_many_country_cache(all_key_list, need_loads=True)
        for allies_country_id, info in zip(all_key_list, country_info_list):
            if info:
                info_dict.update({allies_country_id: CountryInfoList[info_index](**info)})
            else:
                not_found_list.append(allies_country_id)
        if not_found_list:
            not_found_a_c_id_dict = cls.split_allies_country_id(not_found_list)
            country_info = cls.get_many_country_info_from_db(not_found_a_c_id_dict)
            if country_info:
                info_dict.update(country_info)
                tmp_dict = dict()
                for k, v in country_info.items():
                    tmp_dict[k] = v._asdict()
                cls.set_many_country_cache(tmp_dict)
        return info_dict

    @classmethod
    def delete_country_cache(cls, allies_id, country_id):
        """删除缓存"""
        allies_country_id = cls.get_key(allies_id, country_id)
        cls.country_info_cache.delete_country_cache(allies_country_id)
